#!/bin/bash
#############################################
# author:fang
# version : v1.0
# name  : xffmpeg
# dispcripe: use of ffmpeg
# CopyRight@fangyunjiang[42550564@qq.com]
#############################################
source ~/command/common
_oper=0

function show_full_help() {
	echo "查看设备"
	echo "ffmpeg -list_devices true -f dshow -i dummy"
	echo
	echo "转发为位图"
	echo "ffmpeg -i 1.png -pix_fmt rgb24 1.bmp"
	echo
	echo "缩放视频"
	echo "ffmpeg -i 1.mp4 -s 320x240 -y -acodec copy 2.mp4"
	echo "ffmpeg -i 1.mp4 -vf scale=320:240 -y -acodec copy 2.mp4"
	echo "ffmpeg -i 1.mp4 -vf scale=iw/2:ih/2 -y -acodec copy 2.mp4"
	echo "ffmpeg -i 1.mp4 -vf scale=320:-2 -y -acodec copy 2.mp4"
	echo
	echo "按照帧剪切视频图片"
	echo "ffmpeg -i 1.mp4 -vf \"select=between(n\,0\,10)\" -y -acodec copy 2.mp4"
	echo
	echo "按照帧生成图片"
	echo "ffmpeg -i 1.mp4 -vf \"select=between(n\,0\,2)\" -f image2 fang/%02d.jpg"
	echo
	echo "提取关键帧 eq(pict_type\,B) eq(pict_type\,P)"
	echo "ffmpeg -i 2.mp4 -vf select='eq(pict_type\,I)' -vsync 2 -f image2 fang/%02d.jpeg"
	echo
	echo "把视频5-10s和15-20s静音"
	echo "ffmpeg -i 1.mp4 -af \"volume=enable='between(t,5,10)':volume=0, volume=enable='between(t,15,20)':volume=0\" 2.mp4"
	echo
	echo "添加水印"
	echo "ffmpeg -i 2.mp4 -i logo.png -filter_complex \"overlay=W-w-5:H-h-5\" -codec:a copy -y 3.mp4"
	echo "ffmpeg -i 2.mp4 -i logo.png -filter_complex \"overlay=main_w-overlay_w-5:main_h-overlay_h-5\" -codec:a copy -y 3.mp4"
	echo
	echo "去除水印"
	echo "ffmpeg -i 3.mp4 -vf delogo=x=5:y=5:w=72:h=72 4.mp4"
	echo
	echo "视频或图像加上黑边pad, 原视频1920×1080，新视频2000x1160 40x2=2000-1920 40x2=1160-1080"
	echo "ffmpeg -i 2.mp4 -vf pad=2000:1160:40:40:black -y 3.mp4"
	echo
	echo "添加水印，带scale"
	echo "ffmpeg -i 1.mp4 -vf \"movie=test.PNG,scale=100:150[watermask];[in][watermask] overlay=100:100[out]\" -y 2.mp4"
	echo
	echo "切割成m3u8"
	echo "ffmpeg -i 1.mp4 -c:v libx264 -c:a aac -map 0 -f segment -segment_list dist/index.m3u8 -segment_time 5 dist/%03d.ts"
	echo "ffmpeg -i 1.mp4 -codec copy -vbsf h264_mp4toannexb -map 0 -f segment -segment_list m3u8/index.m3u8 -segment_time 10 m3u8/out%03d.ts"
}

function cut_video()
{
	if [ $# != "4" -a $# != "3" ];then
		echo "参数错误，正确格式为：xffmpeg -cut srcVideo [startTime] endTime distVideo"
		exit
	fi
	if [ $# = "3" ];then
		if [ "$1" = "$3" ];then
			echo "不能覆盖源文件"
			exit
		fi
		echo ffmpeg -ss 0 -to $2 -i "$1" -vcodec copy -acodec copy ${3} -y
		ffmpeg -ss 0 -to $2 -i "$1" -vcodec copy -acodec copy ${3} -y
	else
		if [ "$1" = "$4" ];then
			echo "不能覆盖源文件"
			exit
		fi
		echo ffmpeg -ss $2 -to $3 -i "$1" -vcodec libx264 -crf 30 -acodec copy ${4} -y
		ffmpeg -ss $2 -to $3 -i "$1" -vcodec libx264 -crf 30 -acodec copy ${4} -y
	fi
}
function join_video()
{
	local i n arr
	if [ $# -lt 3 ];then
		echo "参数错误，正确格式为：xffmpeg -join srcVideo1 srcVideo2 ..."
		exit
	fi
	n="$#"
	arr=("$@")
	echo "file ${arr[0]}" > .__video_list
	for ((i=1; i<n-1; i++));do
		echo "file ${arr[i]}" >> .__video_list
	done
	echo ffmpeg -f concat -i .__video_list -c copy ${arr[i]} -y
	ffmpeg -f concat -i .__video_list -c copy ${arr[i]} -y
	rm .__video_list
}
function join_video_ex()
{
	local i s n arr extname
	if [ $# != 3 ];then
		echo "参数错误，正确格式为：xffmpeg -joinEx 1 n distVideo"
		exit
	fi
	extname=`__get_extname "$3"`
	s=$1
	n=$2
	echo "file $s.${extname}" > .__video_list
	for ((i=s+1; i<=n; i++));do
		echo "file $i.${extname}" >> .__video_list
	done
	echo ffmpeg -f concat -i .__video_list -c copy "$3" -y
	ffmpeg -f concat -i .__video_list -c copy "$3" -y
	rm .__video_list
}
function concat_image()
{
	local i n arr stack line ow ows max o list
	stack="vstack"
	if [ "$1" = "v" ];then
		stack="vstack"
		shift
	elif [ "$1" = "h" ];then
		stack="hstack"
		shift
	fi
	if [ $# -lt 3 ];then
		echo "参数错误，正确格式为：xffmpeg -concat srcImage1 srcImage2 ..."
		exit
	fi
	n="$#"
	arr=("$@")
	line=""
	if [ "$stack" = "vstack" ];then
		for ((i=0; i<n-1; i++));do
			ow=`ffmpeg -i "${arr[i]}" 2>&1 | grep Video: | grep -Po '\d+x\d+'`
			ow=${ow%%x*}
			ows="$ows $ow"
		done
		ows=($ows)
		max=${ows[0]}
		for o in ${ows[@]};do
			if (( o > max ));then
				max=$o
			fi
		done
		for ((i=0; i<n-1; i++));do
			if [ "$max" != "${ows[i]}" ];then
				scale_video "${arr[i]}" "$max" "xxx${arr[i]}"
				line="${line} -i xxx${arr[i]}"
				list="$list xxx${arr[i]}"
			else
				line="${line} -i ${arr[i]}"
			fi
		done
		echo ffmpeg ${line} -filter_complex ${stack} ${arr[i]} -y
		ffmpeg ${line} -filter_complex ${stack} ${arr[i]} -y
		rm -f ${list}
	else
		for ((i=0; i<n-1; i++));do
			ow=`ffmpeg -i "${arr[i]}" 2>&1 | grep Video: | grep -Po '\d+x\d+'`
			ow=${ow##*x}
			ows="$ows $ow"
		done
		ows=($ows)
		max=${ows[0]}
		for o in ${ows[@]};do
			if (( o > max ));then
				max=$o
			fi
		done
		for ((i=0; i<n-1; i++));do
			if [ "$max" != "${ows[i]}" ];then
				scale_video "${arr[i]}" 0 "$max" "xxx${arr[i]}"
				line="${line} -i xxx${arr[i]}"
				list="$list xxx${arr[i]}"
			else
				line="${line} -i ${arr[i]}"
			fi
		done
		echo ffmpeg ${line} -filter_complex ${stack} ${arr[i]} -y
		ffmpeg ${line} -filter_complex ${stack} ${arr[i]} -y
		rm -f ${list}
	fi
}
function logo_video()
{
	local dist overlay
	if [ $# != "5" -a $# != "7" ];then
		echo "参数错误，正确格式为：xffmpeg -logo video logo logoX logoY [logoWidth logoHeight] distVideo"
		exit
	fi
	if [ $# = "7" ];then
		echo ffmpeg -i $2 -s $5x$6 .__$2
		ffmpeg -i $2 -s $5x$6 .__$2
		dist="$7"
	else
		cp $2 .__$2
		dist="$5"
	fi
	if (($3<0));then
		if (($4<0));then
			overlay="W-w+$3:H-h+$4"
		else
			overlay="W-w+$3:$4"
		fi
	else
		if (($4<0));then
			overlay="$3:H-h+$4"
		else
			overlay="$3:$4"
		fi
	fi
	echo ffmpeg -i "$1" -vf "movie=.__$2[watermark];[in][watermark] overlay=$overlay[out]" "$dist" -y
	ffmpeg -i "$1" -vf "movie=.__$2[watermark];[in][watermark] overlay=$overlay[out]" "$dist" -y
	rm .__$2
}
function cover_video()
{
	local wh
	if [ $# != "3" ];then
		echo "参数错误，正确格式为：xffmpeg -cover srcVideo srcImage distVideo"
		exit
	fi
	get_video_width_height $1 wh

	echo ffmpeg -i "$1" -i "$2" -filter_complex [1:v]scale=${wh}[ovrl],[0:v][ovrl]overlay=enable='between(n\,0\,1)' -y "$3"
	ffmpeg -i "$1" -i "$2" -filter_complex [1:v]scale=${wh}[ovrl],[0:v][ovrl]overlay=enable='between(n\,0\,1)' -y "$3"
	# 不计算宽度
	#ffmpeg -i 1.mp4 -i 1.png -filter_complex overlay=enable='between(n\,0\,1)' -y 2.mp4
	# 只添加封面
	#ffmpeg -i 1.mp4 -i 1.png -map 0 -map 1 -c copy -c:v:1 png -disposition:v:1 attached_pic -y 2.mp4
}
function set_contrast_brightness_video()
{
	if [ $# != "4" ];then
		echo "参数错误，正确格式为：xffmpeg -bright srcVideo contrast brightness distVideo"
		exit
	fi
	echo ffmpeg -i $1 -vf eq=contrast=$2:brightness=$3 -y $4
	ffmpeg -i $1 -vf eq=contrast=$2:brightness=$3 -y $4
}
function get_video_time()
{
	local list sum var
	list=($(ffmpeg -i "$1" 2>&1|grep Duration| cut -d ' ' -f 4 | sed 's/\..*//'|sed 's/:/ /g'))
	if [ -z "$list" ];then
		echo "这不是一个视频文件"
		exit
	fi
	sum=0
	for var in "${list[@]}";do
		((sum=sum*60+var))
	done
	eval $2=$sum
}
function get_video_width_height()
{
	local ret
	ret=$(ffmpeg -i "$1" 2>&1|grep Stream.*Video|cut -d ',' -f 3|sed 's/x/:/'|sed 's/\s//g')
	eval $2="$ret"
}
function set_audio_video()
{
	local vtime atime n joinstr
	if [ $# != "3" ];then
		echo "参数错误，正确格式为：xffmpeg -audio srcVideo srcAudio distVideo"
		exit
	fi
	get_video_time "$1" vtime
	get_video_time "$2" atime

	((n=(vtime-1)/atime+1))

	if ((n>1));then
		joinstr=""
		for ((i=0;i<n;i++));do
			joinstr="$joinstr $2"
		done
		join_video $joinstr __audio.mp3
	else
		cp "$2" __audio.mp3
	fi

	echo ffmpeg -i $1 -c:v copy -an __video.mp4
	ffmpeg -i $1 -c:v copy -an __video.mp4
	echo ffmpeg -i __video.mp4 -i __audio.mp3 -t $vtime -c copy -y $3
	ffmpeg -i __video.mp4 -i __audio.mp3 -t $vtime -c copy -y $3
	#ffmpeg -i __video.mp4 -i __audio.mp3 -t $vtime –vcodec copy –acodec copy -y $3

	rm __audio.mp3
	rm __video.mp4
}
function split_video_audio()
{
	if [ $# != "3" ];then
		echo "参数错误，正确格式为：xffmpeg -split srcVideo video|audio distFile"
		exit
	fi
	if [ "$2" = "video" ];then
		ffmpeg -i "$1" -vcodec copy -an "$3"
	elif [ "$2" = "audio" ];then
		# ffmpeg -i "$1" -acodec copy -vn "$3"
		ffmpeg -i "$1" -b:a 128k "$3"
	else
		echo "参数错误，正确格式为：xffmpeg -split srcVideo video|audio distFile"
	fi
}
function crop_video()
{
	if [ $# = "4" ];then
		if [ "${2/iw/}" != "$2" -o "${3/ih/}" != "$3" ]; then
			echo ffmpeg -i "$1" -vf crop=${2}:${3}:0:0 -y "$4"
			ffmpeg -i "$1" -vf crop=${2}:${3}:0:0 -y "$4"
		else
			echo ffmpeg -i "$1" -vf crop=iw-${2}:ih-${3}:${2}:${3} -y "$4"
			ffmpeg -i "$1" -vf crop=iw-${2}:ih-${3}:${2}:${3} -y "$4"
		fi
		exit
	fi
	if [ $# != "6" ];then
		echo "参数错误，正确格式为：xffmpeg -crop srcVideo x y width height distVideo"
		exit
	fi
	echo ffmpeg -i "$1" -vf crop=${4}:${5}:${2}:${3} -y "$6"
	ffmpeg -i "$1" -vf crop=${4}:${5}:${2}:${3} -y "$6"
}
function scale_video()
{
	local scale ow
	if [ $# = "4" ];then
		if [ "$2" != "0" ];then
			echo ffmpeg -i "$1" -s ${2}x${3} -y -acodec copy "$4"
			ffmpeg -i "$1" -s ${2}x${3} -y -acodec copy "$4"
		else
			ow=`ffmpeg -i "$1" 2>&1 | grep Video: | grep -Po '\d+x\d+'`
			ow=${ow##*x}
			scale=`awk 'BEGIN{printf("%.2f", "'$ow'" / "'$3'")}'`
			echo ffmpeg -i "$1" -vf scale=iw/${scale}:$3 -y -acodec copy "$4"
			ffmpeg -i "$1" -vf scale=iw/${scale}:$3 -y -acodec copy "$4"
		fi
	elif [ $# = "3" ];then
		ow=`ffmpeg -i "$1" 2>&1 | grep Video: | grep -Po '\d+x\d+'`
		ow=${ow%%x*}
		scale=`awk 'BEGIN{printf("%.2f", "'$ow'" / "'$2'")}'`
		echo ffmpeg -i "$1" -vf scale=$2:ih/${scale} -y -acodec copy "$3"
		ffmpeg -i "$1" -vf scale=$2:ih/${scale} -y -acodec copy "$3"
	else
		echo "参数错误，正确格式为：xffmpeg -scale srcVideo width [height] distVideo"
	fi
}
function scale_video_ex() {
	if [ $# = "3" -o $# = "2" ];then
		if ! [ -f "__$1" ];then
			cp "$1" "__$1"
		fi
		scale_video "__$1" $2 $3 $1
	else
		echo "参数错误，正确格式为：xffmpeg -scale srcVideo width [height]"
	fi
}
function reverse_video()
{
	if [ $# != "2" ];then
		echo "参数错误，正确格式为：xffmpeg -reverse srcVideo distVideo"
		exit
	fi
	ffmpeg -i "$1" -vf reverse -y "$2"
}
function fast_video()
{
	local rate
	if [ $# != "3" ];then
		echo "参数错误，正确格式为：xffmpeg -fast rate srcVideo distVideo"
		exit
	fi
	rate=$(echo "scale=6;1/${1}"|bc)
	ffmpeg -i "$2" -filter_complex "[0:v]setpts=${1}*PTS[v];[0:a]atempo=${rate}[a]" -map "[v]" -map "[a]" -y "$3"
}
function get_video_image()
{
	if [ $# != "3" ];then
		echo "参数错误，正确格式为：xffmpeg -image srcVideo time distImage"
		exit
	fi
	ffmpeg -ss $2 -i "$1" -vframes 1 -q:v 2 "$3"
}
function capture_desktop_video()
{
	local microphone
	if [ $# != "1" -a $# != "2" ];then
		echo "参数错误，正确格式为：xffmpeg -c 1.mp4|1.mp3 [1:hasMicrophone]"
		exit
	fi
	# 必须安装 https://github.com/rdp/screen-capture-recorder-to-video-windows-free
	microphone="麦克风阵列 (适用于数字麦克风的英特尔® 智音技术)" # 搜索设备管理器 -> 音频输入和输出 -> 双击micphone -> 详情信息 -> 复制值(V)

	if [ "$1" = *.mp3 ];then
		if [ -z "$2" ];then
			ffmpeg -y -f dshow -i audio="virtual-audio-capturer" "$1"
		else
			ffmpeg -y -f dshow -i audio="${microphone}" -f dshow -i audio="virtual-audio-capturer" -filter_complex amix=inputs=2:duration=first:dropout_transition=0 "$1"
		fi
	else
		if [ -z "$2" ];then
			ffmpeg -y -f dshow -i audio="virtual-audio-capturer":video="screen-capture-recorder" "$1"
		else
			ffmpeg -y -f dshow -i audio="${microphone}" -f dshow -i audio="virtual-audio-capturer" -filter_complex amix=inputs=2:duration=first:dropout_transition=0 -f dshow -i video="screen-capture-recorder" -pix_fmt yuv420p "$1"
		fi
	fi
}
function get_video_info()
{
	n="$#"
	for ((i=0; i<n; i++));do
		if [ "${1%%.png}" != "$1" -o "${1%%.jpg}" != "$1" ];then
			ffmpeg -i "$1" 2>&1 | grep Video: | grep -Po '\d+x\d+'
		else
			# ffprobe -select_streams v:0  -v quiet -show_streams -of json -i "$1"
			# echo ffprobe -v quiet -select_streams v:0 -show_entries stream=nb_frames,width,height,duration -of default=nokey=0:noprint_wrappers=1 "$1"
			ffprobe -v quiet -select_streams v:0 -show_entries stream=nb_frames,width,height,duration -of default=nokey=0:noprint_wrappers=1 "$1"
		fi
		shift
	done
}
function show_help()
{
	local -a list
	list="help"
	list=("${list[@]}" "Usage: xffmpeg [OPTIONS]")
	list=("${list[@]}" "  -logo video logo logoX logoY [logoWidth logoHeight] distVideo: [设置logo -10 -10表示右下角] xffmpeg -logo 1.mp4 1.jpg 10 10 [100 100] 2.mp4")
	list=("${list[@]}" "  -cut srcVideo [startTime] endTime distVideo: [剪切] xffmpeg -cut 1.mp4 05.000 10.0000 2.mp4 ,如果只设置了一个时间，则为endTime")
	list=("${list[@]}" "  -join srcVideo1 srcVideo2 ... distVideo: [连接] xffmpeg -join 1.mp4 2.mp4 3.mp4")
	list=("${list[@]}" "  -joinEx 1 n distVideo: [连接] xffmpeg -joinEx 1 10 2.mp4")
	list=("${list[@]}" "  -cover srcVideo srcImage distVideo: [封面] xffmpeg -cover 1.mp4 1.png 2.mp4")
	list=("${list[@]}" "  -bright srcVideo contrast brightness distVideo: [对比度亮度] xffmpeg -bright 1.mp4 1.1 -0.1 2.mp4")
	list=("${list[@]}" "  -audio srcVideo srcAudio distVideo: [添加音频] xffmpeg -audio 1.mp4 1.mp3 2.mp4")
	list=("${list[@]}" "  -split srcVideo video|audio distFile: [分离音视频] xffmpeg -split 1.mp4 video 2.mp4")
	list=("${list[@]}" "  -crop srcMedia x y width height distMedia: [裁剪视频|图片，可以使用数字和iw,ih的组合，如果只有x,y且是数据则从x,y剪切到左边和底边，如果只有两位数字且是包含iw和ih,则从0,0剪切到这个位置] xffmpeg -crop 1.mp4|1.jpg iw/4 ih/4 iw/2 ih/2 2.mp4|2.jpg; xffmpeg -crop 1.jpg 50 50 2.jpg;  xffmpeg -crop 1.jpg iw-50 iw-50 2.jpg")
	list=("${list[@]}" "  -scale srcMedia width[0] [height] distMedia: [缩放视频|图片，如果没有height，以width为比列缩放，如果width为0，则以height为比例缩放] xffmpeg -scale 1.mp4|1.jpg width height 2.mp4|2.jpg")
	list=("${list[@]}" "  -s srcMedia width[0] [height]: [缩放视频|图片，自动备份文件")
	list=("${list[@]}" "  -reverse srcVideo distVideo: [倒放视频] xffmpeg -reverse 1.mp4 2.mp4")
	list=("${list[@]}" "  -fast rate srcVideo distVideo: [倒放视频] xffmpeg -fast 0.9 1.mp4 2.m4")
	list=("${list[@]}" "  -image srcVideo time distImage: [截图] xffmpeg -image 1.mp4 10 1.jpg")
	list=("${list[@]}" "  -concat [v|h] srcImage1 srcImage2 ... distImage: [横向|纵向连接图片] xffmpeg -concat h 1.jpg 2.jpg 3.jpg")
	list=("${list[@]}" "  -i srcVideo: [查看视频信息]")
	list=("${list[@]}" "  -c distFile [hasMicrophone]: [录制桌面视频] xffmpeg -c 1.mp4|1.mp3")
	list=("${list[@]}" "  -h: show help ")
	list=("${list[@]}" "  --help: show full help ")
	__msgbox "${list[@]}"
	exit
}


function main()
{
	__init_opts "$@"
	__check_opts "-h" && show_help
	__check_opts "--help" && show_full_help
	__check_opts "-cut" && cut_video ${_args_[@]}
	__check_opts "-join" && join_video ${_args_[@]}
	__check_opts "-joinEx" && join_video_ex ${_args_[@]}
	__check_opts "-logo" && logo_video ${_args_[@]}
	__check_opts "-cover" && cover_video ${_args_[@]}
	__check_opts "-bright" && set_contrast_brightness_video ${_args_[@]}
	__check_opts "-audio" && set_audio_video ${_args_[@]}
	__check_opts "-split" && split_video_audio ${_args_[@]}
	__check_opts "-crop" && crop_video ${_args_[@]}
	__check_opts "-scale" && scale_video ${_args_[@]}
	__check_opts "-s" && scale_video_ex ${_args_[@]}
	__check_opts "-reverse" && reverse_video ${_args_[@]}
	__check_opts "-fast" && fast_video ${_args_[@]}
	__check_opts "-image" && get_video_image ${_args_[@]}
	__check_opts "-concat" && concat_image ${_args_[@]}
	__check_opts "-c" && capture_desktop_video ${_args_[@]}
	__check_opts "-i" && get_video_info ${_args_[@]}
}

main "$@"
